#ifndef UI_LOADER_H
#define UI_LOADER_H

#include "glibmm/dispatcher.h"
#include "gtkmm/switch.h"
#include "MultiLineChart.hpp"
#include "BarChart.hpp"
#include "gtkmm/treemodelcolumn.h"
#include <gtkmm.h>
#include <thread>
#include <functional>

class UILoader
{
  public:
    UILoader();
    void Boot();
    virtual ~UILoader();
    void RefreshUI();

    void SetOriImage(int width,int height,unsigned char* img);
    void SetStdImage(int width,int height,unsigned char* img);
    void InputData(float chart1,float chart2,float chart3);

    std::function<void()> funcUIExit;
    std::function<void(std::string)> funcSetStdJoint;
    std::function<void(std::string)> funcSetOriJoint;
    std::function<void(std::string)> funcSetStdVideo;
    std::function<void(std::string)> funcSetOriVideo;
    std::function<void(std::string)> funcSetDiffJoint;

    std::function<void(bool)> funcSetContinue;
    std::function<void()> funcSetPlay;
    std::function<void()> funcSetStop;
    std::function<std::vector<long>(long taskId)> funcSearchHandleFinishItem;
    std::function<std::vector<long>()> funcGetTaskList;
    std::function<std::tuple<std::string/*项目名称*/,std::string/*创建时间*/>(long taskId)> funcGetTaskInfo;
    std::function<std::tuple<long/*学号*/,std::string/*创建时间*/,std::string/*路径*/>(long itemID)> funcGetItemInfo;
  private:
    void signal_activate_app();
    void siganl_click_btnRefreshList();
    
    void signal_click_btnChooseStdVideo();
    void signal_click_btnChooseOriJoint();
    void signal_click_btnChooseStdJoint();
    void signal_click_btnChooseOriVideo();
    void signal_click_btnChooseDiffJoint();
    void signal_click_btnControlStart();
    void signal_click_btnControlStop();
    void draw_stdImage(const Cairo::RefPtr<Cairo::Context>& cr,int width,int height);
    void draw_oriImage(const Cairo::RefPtr<Cairo::Context>& cr,int width,int height);
    bool signal_set_swiControlContinue(bool);
    void signal_activate_listRecord(const Gtk::TreeModel::Path& path,Gtk::TreeViewColumn* column);
    
    void signal_render_glChart1(const Cairo::RefPtr<Cairo::Context>& cr, int width, int height);
    void signal_render_glChart2(const Cairo::RefPtr<Cairo::Context>& cr, int width, int height);
    void signal_render_glChart3(const Cairo::RefPtr<Cairo::Context>& cr, int width, int height);

    void signal_refresh();

    Glib::RefPtr<Gtk::Application> app;
    std::thread workThread;
    Gtk::Window* mainWindow;
    Gtk::TreeView* listRecord;
    Gtk::Button* btnChooseStdVideo;
    Gtk::Button* btnChooseOriVideo;
    Gtk::Button* btnChooseOriJoint;
    Gtk::Button* btnChooseStdJoint;
    Gtk::Button* btnChooseDiffJoint;
    Gtk::Switch* swiControlContinue;
    Gtk::Button* btnControlStart;
    Gtk::Button* btnControlStop;
    Gtk::Button* btnRefreshList;

    Gtk::DrawingArea* videoOri;
    Gtk::DrawingArea* videoStd;
    Gtk::DrawingArea *glChart1,*glChart2,*glChart3;
    Glib::RefPtr<Gtk::Builder> refBuilder;

    std::mutex stdImageMut,oriImageMut;
    Glib::RefPtr<Gdk::Pixbuf> stdImage,oriImage;

    std::unique_ptr<Glib::Dispatcher> patch_refresh;

    glMultiLineChart chart1,chart2;
    BarChart chart3;

    template<class T> T* GetInstance(const char* name);
    template<class T> T* GetInstancePlus(T* type,const char* name);

    class ModelColumns:public Gtk::TreeModelColumnRecord
    {
      public:
        ModelColumns()
        {
          add(m_col_name);
          add(m_col_time);
          add(level);
          add(path);
        }
        Gtk::TreeModelColumn<Glib::ustring> m_col_name;
        Gtk::TreeModelColumn<Glib::ustring> m_col_time;
        Gtk::TreeModelColumn<int> level;
        Gtk::TreeModelColumn<Glib::ustring> path;
    };
    ModelColumns m_columns;
    Glib::RefPtr<Gtk::TreeStore> m_refTreeModel;

};

#endif
